package fileCommodore.model;

import java.util.*;

import org.apache.commons.vfs.*;

public class SingleDirectoryMonitor implements Runnable, FileMonitor {

	Thread t;
	FileObject d;
	FileListener fl;

	long lastCheck = -1;

	HashSet<FileObject> children = new HashSet<FileObject>();

	public SingleDirectoryMonitor(FileListener listener) {
		fl = listener;
	}

	public void setDirectory(FileObject dir) {
		removeFile(d);
		addFile(dir);
	}

	public synchronized void run() {
		try {
			while (null != d) {
				try {
					d.refresh();
					FileObject[] currentChildren = d.getChildren();

					HashSet<FileObject> newChildren = new HashSet<FileObject>();
					HashSet<FileObject> additions = new HashSet<FileObject>();
					HashSet<FileObject> deletions = new HashSet<FileObject>(
							children);

					for (FileObject child : currentChildren) {
						newChildren.add(child);
						deletions.remove(child);
						additions.add(child);

						if (children.contains(child)) {
							long lastChanged = child.getContent()
									.getLastModifiedTime();
							if (lastCheck != -1 && lastChanged > lastCheck) {
								FileChangeEvent fce = new FileChangeEvent(child);
								try {
									fl.fileChanged(fce);
								} catch (Exception e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}
						}
					}

					for (FileObject child : deletions) {
						FileChangeEvent fce = new FileChangeEvent(child);
						try {
							fl.fileDeleted(fce);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}

					additions.removeAll(children);
					for (FileObject child : additions) {
						FileChangeEvent fce = new FileChangeEvent(child);
						try {
							fl.fileCreated(fce);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}

					children = newChildren;
					lastCheck = System.currentTimeMillis();
				} catch (FileSystemException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				wait(100);
			}
		} catch (InterruptedException ex) {
		}
	}

	public void addFile(FileObject arg0) {
		if (null != t) {
			throw new IllegalStateException(
					"Stop the previous SingleDirectoryMonitor thread before starting a new one!");
		}

		d = arg0;

		children.clear();
		try {
			for (FileObject child : d.getChildren()) {
				children.add(child);
			}
		} catch (FileSystemException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		t = new Thread(this);
		t.start();
	}

	public void removeFile(FileObject arg0) {
		d = null;
		t.interrupt();
		t = null;
	}
}
